﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace TAD
{
    public class ListaDinamica
    {
        // Fields
        private const int _defaultCapacity = 13;
        private object[] _items;
        private int _size;
        [NonSerialized]
        private int _version;
        private static readonly object[] emptyArray = new object[0];


        // Properties
        public virtual int Capacity
        {
            get
            {
                return this._items.Length;
            }
            set
            {
                if (value != this._items.Length)
                {
                    if (value < this._size)
                    {
                        throw new ArgumentOutOfRangeException("valor inválido");
                    }
                    if (value > 0)
                    {
                        object[] destinationArray = new object[value];
                        if (this._size > 0)
                        {
                            Array.Copy(this._items, 0, destinationArray, 0, this._size);
                        }
                        this._items = destinationArray;
                    }
                    else
                    {
                        this._items = new object[4];
                    }
                }
            }
        }

        public virtual int Count
        {
            get
            {
                return this._size;
            }
        }


        // Methods
        public ListaDinamica()
        {
            this._items = emptyArray;
        }

        public ListaDinamica(int capacity)
        {
            if (capacity < 0)
            {
                throw new ArgumentOutOfRangeException("Argumento fora no limite da array");
            }
            this._items = new object[capacity];
        }

        public virtual int Add(Carta value)
        {
            if (this._size == this._items.Length)
            {
                this.EnsureCapacity(this._size + 1);
            }
            this._items[this._size] = value;
            this._version++;
            return this._size++;
        }

        public virtual void AddRange(ICollection c)
        {
            this.InsertRange(this._size, c);
        }   

        public virtual void InsertRange(int index, ICollection c)
        {
            if (c == null)
            {
                throw new ArgumentNullException("Argumento nulo");
            }
            if ((index < 0) || (index > this._size))
            {
                throw new ArgumentOutOfRangeException("indice fora dos limites da array");
            }
            int count = c.Count;
            if (count > 0)
            {
                this.EnsureCapacity(this._size + count);
                if (index < this._size)
                {
                    Array.Copy(this._items, index, this._items, index + count, this._size - index);
                }
                object[] array = new object[count];
                c.CopyTo(array, 0);
                array.CopyTo(this._items, index);
                this._size += count;
                this._version++;
            }
        }

        public virtual void Insert(int index, object value)
        {
            if ((index < 0) || (index > this._size))
            {
                throw new ArgumentOutOfRangeException("Argumento fora dos limites da array");
            }
            if (this._size == this._items.Length)
            {
                this.EnsureCapacity(this._size + 1);
            }
            if (index < this._size)
            {
                Array.Copy(this._items, index, this._items, index + 1, this._size - index);
            }
            this._items[index] = value;
            this._size++;
            this._version++;
        }

        public virtual void Clear()
        {
            if (this._size > 0)
            {
                Array.Clear(this._items, 0, this._size);
                this._size = 0;
            }
            this._version++;
        }

        private void EnsureCapacity(int min)
        {
            if (this._items.Length < min)
            {
                int num = (this._items.Length == 0) ? 4 : (this._items.Length * 2);
                if (num < min)
                {
                    num = min;
                }
                this.Capacity = num;
            }
        }

        public virtual int IndexOf(object value)
        {
            return Array.IndexOf(this._items, value, 0, this._size);
        }

        public virtual int IndexOf(object value, int startIndex)
        {
            if (startIndex > this._size)
            {
                throw new ArgumentOutOfRangeException("Argumento fora dos limites da coleção");
            }
            return Array.IndexOf(this._items, value, startIndex, this._size - startIndex);
        }

        public virtual int IndexOf(object value, int startIndex, int count)
        {
            if (startIndex > this._size)
            {
                throw new ArgumentOutOfRangeException("Argumento fora dos limites da coleção");
            }
            if ((count < 0) || (startIndex > (this._size - count)))
            {
                throw new ArgumentOutOfRangeException("Argumento fora dos limites da coleção");
            }
            return Array.IndexOf(this._items, value, startIndex, count);
        }

        public virtual void Remove(object obj)
        {
            int index = this.IndexOf(obj);
            if (index >= 0)
            {
                this.RemoveAt(index);
            }
        }

        public virtual void RemoveAt(int index)
        {
            if ((index < 0) || (index >= this._size))
            {
                throw new ArgumentOutOfRangeException("Indice fora dos limites da array");
            }
            this._size--;
            if (index < this._size)
            {
                Array.Copy(this._items, index + 1, this._items, index, this._size - index);
            }
            this._items[this._size] = null;
            this._version++;
        }

        public virtual void RemoveRange(int index, int count)
        {
            if ((index < 0) || (count < 0))
            {
                throw new ArgumentOutOfRangeException("Indice fora dos limites da array");
            }
            if ((this._size - index) < count)
            {
                throw new ArgumentException("Argumento inválido");
            }
            if (count > 0)
            {
                int num = this._size;
                this._size -= count;
                if (index < this._size)
                {
                    Array.Copy(this._items, index + count, this._items, index, this._size - index);
                }
                while (num > this._size)
                {
                    this._items[--num] = null;
                }
                this._version++;
            }
        }
    }
}
